<template></template>

<script setup lang="js">
import * as THREE from 'three'
import {  defineProps,watchEffect } from 'vue'
import { useTresContext } from '@tresjs/core'
import {gsap } from 'gsap'

const { scene} = useTresContext()
const nbObjects = 800

let spriteMap
const props = defineProps({
    opacity: {
        type: Number,
        default: 0.8,
    },

})

function getRandomVec3() {
    const u = Math.random()
    const v = Math.random()
    const theta = u * 2.0 * Math.PI
    const phi = Math.acos(2.0 * v - 1.0)
    const r = Math.cbrt(Math.random())
    const sinTheta = Math.sin(theta)
    const cosTheta = Math.cos(theta)
    const sinPhi = Math.sin(phi)
    const cosPhi = Math.cos(phi)
    const x = r * sinPhi * cosTheta
    const y = r * sinPhi * sinTheta
    const z = r * cosPhi
    return { x, y, z }
}
function Truc() {
    this.init()
    this.shuffle()
}
function init() {

    spriteMap = new THREE.Texture()
    const bubble = new Image()
    bubble.src =
        ''
    bubble.onload = function () {
        spriteMap.image = bubble
        spriteMap.needsUpdate = true
    }


    for (let i = 0; i < nbObjects; i++) {
        const object = new Truc()
        scene.value.add(object.sprite)
    }
}

function getRandomHexColor() {
    const randomColor = Math.floor(Math.random() * 16777215).toString(16) // 16777215 = FFFFFF
    return `#${randomColor.padStart(6, '0')}` // 确保颜色长度为6位
}
Truc.prototype.init = function () {
    this.material = new THREE.SpriteMaterial({
        color: getRandomHexColor(),
        map: spriteMap,
        transparent: true,
        opacity: 1,
        depthTest: false,
        depthWrite: false,
        blending: THREE.AdditiveBlending,
    })
    this.sprite = new THREE.Sprite(this.material)
}

function rnd(max, negative) {
    return negative ? Math.random() * 2 * max - max : Math.random() * max
}
Truc.prototype.shuffle = function () {

    this.scale1 = 0.1
    this.scale2 = 2 + rnd(3)
    this.sprite.scale.set(this.scale1, this.scale1, 1)

    const rndv = getRandomVec3()
    this.sprite.position.set(rndv.x, rndv.y, rndv.z).multiplyScalar(50)
    this.sprite.position.y -= 25

    this.material.opacity = props.opacity

    this.tt = this.scale2
    gsap.to(this.sprite.scale, 1, { x: this.scale2, y: this.scale2, ease:'power1.inOut' })
    gsap.to(this.sprite.position, this.scale2, { y: this.sprite.position.y + 100, ease:'power1.inOut' })


    this.t1 = 1
    gsap.to(this.sprite.position, this.t1, {
        x: this.sprite.position.x + rnd(10, true),
        z: this.sprite.position.z + rnd(10, true),
        ease: 'power1.inOut',
        repeat: Math.floor(this.tt / this.t1 / 2),
        yoyo: true,
    })

    gsap.to(this.material, 1, {
        opacity: 0,
        delay: this.tt - 1,
        ease: 'power1.inOut',
        onCompleteParams: [this],
        onComplete (o) {
            o.shuffle()
        },
    })
}



init()
function setOpacityForScene(scene, opacityValue) {
  scene.traverse((child) => {
    if (child.isMesh) {
      if (Array.isArray(child.material)) {

        child.material.forEach((material) => {
          material.transparent = true
          material.opacity = opacityValue
        })
      } else {
        child.material.transparent = true
        child.material.opacity = opacityValue
      }
    }
  })
}

watchEffect(() => {
    if (props.opacity) {
      setOpacityForScene(scene.value, props.opacity)
    }

})
</script>
